package com.louis.ylog;

import com.dianping.cat.Cat;
import com.dianping.cat.CatConstants;
import com.dianping.cat.configuration.NetworkInterfaceManager;
import com.dianping.cat.message.Event;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.MessageTree;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.MDC;
import org.slf4j.Marker;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class TraceContext {

    private static boolean catEnable;

    private static boolean elkEnable;

    private static String appName;

    private static String env;

    private static final String ContextSerialNum="ContextSerialNum";
    private static final String ContextThreadId="ContextThreadId";
    private static final String ContextThreadName="ContextThreadName";

    private static final String ContextSerialNumberFormat="%s_%s";

    private static final ThreadLocal<Map<String, String>> mycontext = ThreadLocal.withInitial(() -> getInitialContext());

    private static final ThreadLocal<String> rootTransType = ThreadLocal.withInitial(() -> "");

    public static void setRootTransType(String catTitle){
        rootTransType.set(catTitle);
    }

    public static String getRootTransType(){
        return rootTransType.get();
    }

    private static Map<String, String> getInitialContext(){
        Map<String,String> init=new HashMap<>();
        try {
            Map<String, String> constEnv = getConstEnv();
            Map<String, String> catEnv=getCatEnv();
            if(!CollectionUtils.isEmpty(catEnv)){
                constEnv.putAll(catEnv);
            }
            init=constEnv;
            refreshMDC(init);
        }catch (Exception ex){
//            log.warn("初始化context异常",ex);
        }
        return init;
    }

    private static Map<String,String> getCatEnv(){
        Map<String,String> init=new HashMap<>();
        try {
            if(isCatEnable()){
                MessageTree tree = Cat.getManager().getThreadLocalMessageTree();
                String messageId = Cat.getCurrentMessageId();
                if (messageId == null) {
                    messageId = Cat.createMessageId();
                    tree.setMessageId(messageId);
                }
                String childId = Cat.createMessageId();
                String root = tree.getRootMessageId();
                if (root == null) {
                    root = messageId;
                }
                init.put("CatRoot",root);
                init.put("CatChildId",childId);
                init.put("CatMessageId",messageId);
            }
        }catch (Exception ex){
//            log.warn("获取cat环境异常",ex);
        }
        return init;
    }

    private static  Map<String, String> getConstEnv(){
        Map<String,String> init=new HashMap<>();
        try {
            init.put(ContextSerialNum,String.format(ContextSerialNumberFormat,System.currentTimeMillis(), UUID.randomUUID().toString()));
            init.put(ContextThreadId,String.valueOf(Thread.currentThread().getId()));
            init.put(ContextThreadName,String.valueOf(Thread.currentThread().getName()));

            init.put("AppName",appName);
            init.put("Env",env);

            init.put("ServerIp",NetworkInterfaceManager.INSTANCE.getLocalHostAddress());
            init.put("ServerName",NetworkInterfaceManager.INSTANCE.getLocalHostName());
        }catch (Exception ex){
//            log.warn("获取运行环境参数异常",ex);
        }
        return init;
    }

    private static void refreshMDC(Map<String, String> contextMap){
        MDC.setContextMap(contextMap);
    }

    private static void refreshMDC(){
        refreshMDC(mycontext.get());
    }

    public static Map<String,String> getAll(){
        if(mycontext.get()==null){
            return new HashMap<>();
        }
        return mycontext.get();
    }

    public static void setAppName(String currentAppName){
        appName=currentAppName;
    }

    public static void setEnv(String currentEnv){
        env=currentEnv;
    }

    public static void setCatEnable(boolean currentCatEnable){
        catEnable=currentCatEnable;
    }

    public static boolean isCatEnable(){
        return catEnable;
    }

    public  static void setElkEnable(boolean currentElkEnable){
        elkEnable=currentElkEnable;
    }

    public static boolean isElkEnable(){
        return elkEnable;
    }

    public static String getAppName(){
        return appName;
    }

    public static String getEnv(){
        return env;
    }

    /**
     * 根据key获取值
     * @param key
     * @return
     */
    public static String getValue(String key) {
        if(mycontext.get() == null) {
            return null;
        }
        return mycontext.get().get(key);
    }

    /**
     * 存储
     * @param key
     * @param value
     * @return
     */
    public static void setValue(String key, String value) {
        Map<String, String> cacheMap = mycontext.get();
        if(cacheMap == null) {
            cacheMap = getInitialContext();
            mycontext.set(cacheMap);
        }
        if(StringUtils.isBlank(key)){
            key="N/A";
        }
        if(StringUtils.isBlank(value)){
            value="N/A";
        }
        cacheMap.put(key, value);
        refreshMDC();
    }

    /**
     * 根据key移除值
     * @param key
     */
    public static void removeValue(String key) {
        Map<String, String> cacheMap = mycontext.get();
        if(cacheMap != null) {
            cacheMap.remove(key);
        }
        refreshMDC();
    }

    /**
     * 重置
     */
    public static void reset() {
        mycontext.set(getInitialContext());
    }

    public static void confirmInitialed(){
        if(CollectionUtils.isEmpty(mycontext.get())){
            reset();
        }
    }

}
